#pragma once

#include <stdexcept>
#include <vector>

// #include "rtda/slot.hpp"
#include "slot.hpp"

namespace jvm {
    namespace rtda {

        class Frame;
        class Thread;

        class OperandStack {
        public:
            explicit OperandStack(size_t size) : _top(0), _slots(size) {}

            OperandStack(const OperandStack&) = delete; // 禁止拷贝构造
            OperandStack& operator=(const OperandStack&) = delete; // 禁止拷贝赋值

            OperandStack(OperandStack&&) = default;
            OperandStack& operator=(OperandStack&&) = default;

            void clear();

            void pushInt(const int32_t& value);
            int32_t popInt();

            void pushFloat(const float& value);
            float popFloat();

            void pushLong(const int64_t& value);
            int64_t popLong();

            void pushDouble(const double& value);
            double popDouble();

            void pushRef(heap::ObjectPtr ref);
            heap::ObjectPtr popRef();

            void pushSlot(const Slot& slot);
            Slot popSlot();

            void pushBoolean(const bool& val);
            bool popBoolean();

            // 获取栈顶第n个位置 从0开始
            heap::ObjectPtr getRefFromTop(uint32_t n) const;

            std::vector<Slot>& get_slots();

            void printAll() const;

        private:
            size_t _top; // 指向栈顶位置，栈顶位置不存放数据
            std::vector<Slot> _slots;
        };

    } // namespace rtda
} // namespace jvms
